import localforage from 'localforage';

// 配置 localforage 实例，用于存储语言包数据
const i18nCache = localforage.createInstance({
  name: 'i18n_cache', // 数据库名称
  storeName: 'translations', // 数据存储区名称
  description: 'Cache for i18n translation data',
});

// 缓存元数据的前缀，用于存储版本和时间戳
const META_KEY_PREFIX = 'i18n_meta_';
// 默认缓存有效期：7天（毫秒）
const DEFAULT_CACHE_DURATION = 7 * 24 * 60 * 60 * 1000;

/**
 * 比较两个版本号的大小。
 * 支持语义化版本号（major.minor.patch）的比较。
 * @param {string} v1 - 第一个版本号字符串。
 * @param {string} v2 - 第二个版本号字符串。
 * @returns {number} 如果 v1 > v2 返回 1，如果 v1 < v2 返回 -1，如果 v1 == v2 返回 0。
 */
function compareVersions(v1, v2) {
  const parts1 = (v1 || '').split('.').map(Number);
  const parts2 = (v2 || '').split('.').map(Number);

  for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
    const part1 = parts1[i] || 0;
    const part2 = parts2[i] || 0;

    if (part1 > part2) return 1;
    if (part1 < part2) return -1;
  }
  return 0;
}

export const cacheManager = {
  /**
   * 从缓存中获取数据。
   * 会检查缓存的版本和时间戳是否过期。
   * @param {string} key - 缓存键。
   * @param {string} [currentVersion] - 当前数据的最新版本号，用于版本比较。如果提供，则会进行版本过期检查。
   * @returns {Promise<any|null>} 缓存的数据，如果缓存不存在或已过期则返回 null。
   */
  async get(key, currentVersion) {
    try {
      // 尝试获取缓存的元数据（版本和时间戳）
      const meta = await i18nCache.getItem(META_KEY_PREFIX + key);
      if (!meta) {
        // 没有元数据，说明没有缓存
        return null;
      }

      const { version, timestamp } = meta;

      // 1. 检查版本是否过期（如果提供了 currentVersion）
      // 如果当前版本比缓存中的版本新，则认为缓存过期
      if (currentVersion && compareVersions(currentVersion, version) > 0) {
        console.log(
          `[Cache] Key '${key}' version outdated. Cached: ${version}, Current: ${currentVersion}. Removing old cache.`,
        );
        await this.remove(key); // 版本过期，移除旧缓存
        return null;
      }

      // 2. 检查时间是否过期
      // 如果当前时间超过了缓存的有效期，则认为缓存过期
      if (Date.now() - timestamp > DEFAULT_CACHE_DURATION) {
        console.log(`[Cache] Key '${key}' time expired. Removing old cache.`);
        await this.remove(key); // 时间过期，移除旧缓存
        return null;
      }

      // 如果缓存未过期，则获取实际数据
      const data = await i18nCache.getItem(key);
      if (data) {
        console.log(`[Cache] Successfully retrieved '${key}' from cache.`);
        return data;
      }
      return null;
    } catch (error) {
      console.error(`[Cache] Error getting '${key}' from cache:`, error);
      // 发生错误时，视为缓存不可用，返回 null
      return null;
    }
  },

  /**
   * 将数据存入缓存。
   * 同时会存储数据的版本号和当前时间戳作为元数据。
   * @param {string} key - 缓存键。
   * @param {any} value - 要缓存的数据。
   * @param {string} version - 数据对应的版本号。
   * @returns {Promise<void>}
   */
  async set(key, value, version) {
    try {
      // 存储实际数据
      await i18nCache.setItem(key, value);
      // 存储元数据（版本和时间戳）
      await i18nCache.setItem(META_KEY_PREFIX + key, {
        version,
        timestamp: Date.now(),
      });
      console.log(
        `[Cache] Successfully set '${key}' in cache with version '${version}'.`,
      );
    } catch (error) {
      console.error(`[Cache] Error setting '${key}' in cache:`, error);
    }
  },

  /**
   * 从缓存中移除指定键的数据及其元数据。
   * @param {string} key - 要移除的缓存键。
   * @returns {Promise<void>}
   */
  async remove(key) {
    try {
      await i18nCache.removeItem(key);
      await i18nCache.removeItem(META_KEY_PREFIX + key);
      console.log(`[Cache] Successfully removed '${key}' from cache.`);
    } catch (error) {
      console.error(`[Cache] Error removing '${key}' from cache:`, error);
    }
  },

  /**
   * 清空所有 i18n 相关的缓存数据。
   * @returns {Promise<void>}
   */
  async clear() {
    try {
      // localforage 的 clear 方法会清空当前实例的所有数据
      await i18nCache.clear();
      console.log('[Cache] All i18n cache cleared.');
    } catch (error) {
      console.error('[Cache] Error clearing cache:', error);
    }
  },
};
